<template>
  <div>
    <!-- 三级分类查询全局组件 -->
    <Category :scene="scene" />

    <!-- 卡片展示组件 -->
    <el-card class="el_card_table">
      <!-- 展示属性与属性值表单的结构 -->
      <div v-show="scene === 0">
        <el-button
          type="primary"
          icon="Plus"
          class="el_card_btn_add"
          :disabled="!categoryStore.category3Id"
          @click="addAttr"
        >
          添加属性
        </el-button>
        <el-table
          border
          stripe
          :data="attrArr"
          v-if="categoryStore.category3Id"
        >
          <el-table-column
            label="序号"
            width="100"
            align="center"
            type="index"
          ></el-table-column>
          <el-table-column
            label="属性名称"
            width="250"
            prop="attrName"
            align="center"
          ></el-table-column>
          <el-table-column
            label="属性值列表"
            prop="attrValueList"
            align="center"
          >
            <template #default="{ row }">
              <el-tag
                class="el_table_tag"
                v-for="(item, index) in row.attrValueList"
                :key="item.id"
                :color="getColorByIndex(index)"
              >
                {{ item.valueName }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="250" align="center">
            <template #default="{ row }">
              <el-button type="warning" icon="Edit" @click="updateAttr(row)">
                修改
              </el-button>
              <el-popconfirm
                :title="`你确定要删除${row.attrName}属性吗`"
                icon="Delete"
                width="250"
                @confirm="deleteAttr(row.id)"
              >
                <template #reference>
                  <el-button type="danger" icon="Delete">删除</el-button>
                </template>
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <el-empty v-else />
      </div>

      <!-- 展示添加属性与修改属性的结构 -->
      <div v-show="scene === 1">
        <el-form :inline="true">
          <el-form-item label="属性名称">
            <el-input
              placeholder="请输入属性名称"
              v-model="attrParams.attrName"
            />
          </el-form-item>
        </el-form>
        <el-button
          type="primary"
          icon="Plus"
          :disabled="!attrParams.attrName.trim()"
          @click="addAttrValue"
        >
          添加属性值
        </el-button>
        <!--<el-button type="info" @click="cancel">取消</el-button>-->
        <el-table
          class="el_table_attr_value"
          border
          stripe
          :data="attrParams.attrValueList"
        >
          <el-table-column
            label="序号"
            width="100"
            align="center"
            type="index"
          ></el-table-column>
          <el-table-column label="属性值名称" align="center">
            <template #default="{ row, $index }">
              <el-input
                :ref="(vc: any) => inputArr[$index] = vc"
                v-if="row.flag"
                @blur="toLook(row, $index)"
                size="small"
                placeholder="请输入属性值名称"
                v-model="row.valueName"
              />
              <div v-else @click="toEdit(row, $index)">{{ row.valueName }}</div>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="250" align="center">
            <template #default="{ row, $index }">
              <el-button
                type="danger"
                icon="Delete"
                @click="attrParams.attrValueList?.splice($index, 1)"
              />
            </template>
          </el-table-column>
        </el-table>
        <el-button
          type="primary"
          :disabled="!attrParams.attrValueList?.length > 0"
          @click="saveAttr"
        >
          保存
        </el-button>
        <el-button type="info" @click="cancel">取消</el-button>
      </div>
    </el-card>
  </div>
</template>

<script setup lang="ts">
// 引入分类相关的仓库
import useCategoryStore from '@/store/modules/category'
// 引入获取属性与属性值的接口方法
import {
  reqGetAttrList,
  reqAddOrUpdateAttr,
  reqDeleteAttr,
} from '@/api/product/attr'
import type { AttrResponseData, Attr, AttrValue } from '@/api/product/attr/type'
// 引入组合式 API 函数 watch
import { watch, ref, reactive, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'

// 获取分类相关的仓库
let categoryStore = useCategoryStore()

// 准备一个数组，用来存储对应的组件实例 el-input
let inputArr = ref<any>([])

// 定义卡片内容切换的控制变量，scene 为 0，展示 table 组件，为 1 则展示添加或修改结构组件
let scene = ref<number>(0)
// 收集新增的属性的数据
let attrParams = reactive<Attr>({
  attrName: '',
  attrValueList: [],
  categoryId: '',
  categoryLevel: 3,
})

// 存储已有的属性和属性值
let attrArr = ref<Attr[]>([])

// tag 标签的颜色数组
const colors = ['#5de627', '#1ed0ef', '#f4ce0e', '#f6812e', '#0768fb']
// tag 标签的颜色展示方法
const getColorByIndex = (index: number) => {
  // 确保颜色数组的索引不会超出范围，可循环或按需处理
  return colors[index % colors.length]
}

// 添加属性按钮的点击事件
const addAttr = () => {
  // 每次点击的时候先清空数据再进行收集
  attrParams.attrName = ''
  attrParams.attrValueList = []
  attrParams.id = ''
  // 点击按钮的时候收集新增属性所属的三级分类的 ID
  attrParams.categoryId = categoryStore.category3Id
  scene.value = 1
}

// 修改属性按钮的点击事件
const updateAttr = (row: Attr) => {
  scene.value = 1
  // 将已有的属性对象赋值给 attrParams 即可 【使用 ES6 语法 Object.assign 进行对象的合并】
  // Object.assign 浅拷贝，有坑。通过 JSON 可以实现深拷贝，解决坑
  Object.assign(attrParams, JSON.parse(JSON.stringify(row)))
}

// 删除属性按钮的点击事件
const deleteAttr = async (attrId: number | string) => {
  let result: any = await reqDeleteAttr(attrId)
  if (result.code === 200) {
    ElMessage.success('删除属性成功')
  } else {
    ElMessage.error('删除属性失败')
  }
  await getAttrList()
}

// 添加属性值按钮的点击事件
const addAttrValue = () => {
  // 点击添加属性值按钮的时候，向属性值数组中添加一个属性值对象
  attrParams.attrValueList.push({
    valueName: '',
    flag: true,
  })
  // 获取最后一个 el-input 组件，自动聚焦
  nextTick(() => {
    inputArr.value[attrParams.attrValueList.length - 1].focus()
  })
}

// 保存按钮的点击事件
const saveAttr = async () => {
  // 发送请求
  let result: any = await reqAddOrUpdateAttr(attrParams)
  if (result.code === 200) {
    ElMessage.success(attrParams.id ? '修改属性成功' : '添加属性成功')
  } else {
    ElMessage.error(attrParams.id ? '修改属性失败' : '添加属性失败')
  }
  scene.value = 0
  await getAttrList()
}

// 取消按钮的点击回调
const cancel = () => {
  scene.value = 0
}

// 表单的属性值元素失去焦点的回调
const toLook = (row: AttrValue, $index: number) => {
  // 非法情况判断
  if (row.valueName.trim() === '') {
    // 删除掉属性值为空的元素
    attrParams.attrValueList?.splice($index, 1)
    ElMessage.error('属性值名称不能为空')
    return
  }
  // 判断添加的属性值是否是重复添加
  let repeat = attrParams.attrValueList?.find((item) => {
    // 如果当前遍历到的元素不等于当前点击的元素，则进行判断。也就是自身不和自身进行判断
    if (item != row) {
      return item.valueName === row.valueName
    }
  })
  if (repeat) {
    // 删除掉属性值重复的元素
    attrParams.attrValueList?.splice($index, 1)
    ElMessage.error('属性值不能重复')
    return
  }
  row.flag = false
}

// 表单的属性值元素点击的回调
const toEdit = (row: AttrValue, $index: number) => {
  row.flag = true
  // nextTick() 函数，会在下一次 DOM 更新之后执行。响应式数据发生变化，获取更新后的 DOM 实例（组件实例）
  nextTick(() => {
    inputArr.value[$index].focus()
  })
}

// 监听仓库中三级分类 ID 的变化
watch(
  () => categoryStore.category3Id,
  () => {
    // 清空上一次查询的属性与属性值
    attrArr.value = []
    // 只有三级分类 ID 存在才去查询
    if (!categoryStore.category3Id) return
    // 调用获取属性与属性值的接口方法
    getAttrList()
  },
)

// 当路由组件销毁的时候，把仓库中三级分类相关的数据清空
onBeforeUnmount(() => {
  // 清空分类仓库中的数据
  categoryStore.$reset()
})

// 获取属性与属性值的接口方法
const getAttrList = async () => {
  const { category1Id, category2Id, category3Id } = categoryStore
  let result: AttrResponseData = await reqGetAttrList(
    category1Id,
    category2Id,
    category3Id,
  )
  if (result.code === 200) {
    attrArr.value = result.data
  }
}
</script>

<style scoped>
.el_card_table {
  margin: 10px 0;
}
.el_card_btn_add {
  margin-bottom: 10px;
}
.el_table_tag {
  margin: 5px;
  color: black;
}
.el_table_attr_value {
  margin: 20px 0;
}
</style>
